package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.cart.client.CartInfoFeignClient;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.user.client.UserInfoFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/order")
public class OrderInfoApiController {
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private CartInfoFeignClient cartInfoFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderInfoService orderInfoService;

    //去结算页面
    @GetMapping("/trade")
    public Map trade(HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        Map result = new HashMap();
        //1 收货地址
        List<UserAddress> userAddressList = userInfoFeignClient.getUserAddressList();
        result.put("userAddressList", userAddressList);
        //2 商品清单
        List<CartInfo> cartInfoList = cartInfoFeignClient.getCartInfoListByChecked();
        //页面实质要的是detailArrayList
        List<OrderDetail> detailArrayList = cartInfoList.stream().map(cartInfo -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());
            return orderDetail;
        }).collect(Collectors.toList());
        result.put("detailArrayList", detailArrayList);
        //3 小计
        long totalNum = detailArrayList.stream().collect(Collectors.summarizingInt(OrderDetail::getSkuNum)).getSum();
        System.out.println("商品的件数 = " + totalNum);
        //总金额  totalAmount
        BigDecimal totalAmount = new BigDecimal("0");
        //stream()方式
//        BigDecimal reduce = detailArrayList.stream().map(orderDetail ->
//                orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()))
//        ).reduce(BigDecimal.ZERO, BigDecimal::add);
        for (OrderDetail orderDetail : detailArrayList) {
            totalAmount = totalAmount.add(orderDetail.getOrderPrice().
                    multiply(new BigDecimal(orderDetail.getSkuNum())));
        }
        result.put("totalNum", totalNum);
        result.put("totalAmount", totalAmount);
        //4 交易号 订单号
        //4.1 UUID
        //4.2 时间戳
        //4.3 MD5(userId+skuId)
        String uuid = UUID.randomUUID().toString();
        //供提交时与页面隐藏的订单号比较 验证一次后应手动删除
        //同一个用户下次来到结算页面时会覆盖原有的值供比较使用
        redisTemplate.opsForValue().set("tradeNo:" + userId, uuid);
        result.put("tradeNo", uuid);
        //4.4 setnx 提交过一次就不能提交了 但是什么时候删除?
        return result;
    }

    @PostMapping("/auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo, String tradeNo, HttpServletRequest request) {//uuid
        String userId = AuthContextHolder.getUserId(request);
        //1:校验交易号是否正确 不正确/重复提交->不可提交
        if (StringUtils.isEmpty(tradeNo)) {//什么情况下交易号可能为空???直接抓取路径提交订单,不经过"去结算页面"的过程
            return Result.fail().message("交易号不能为空!");
        } else {
            Object no = redisTemplate.opsForValue().get("tradeNo:" + userId);
            if (StringUtils.isEmpty(no)) {//缓存中交易号为空 情况:提交后网卡了没有跳转->提交 或 提交->返回->提交 或 手速太快 等等
                //缓存中没有 证明已经提交了 应禁止重复提交
                return Result.fail().message("不要重复提交订单!");
            } else {
                //好像不比也可以...
                if (!tradeNo.equals(no)) {
                    return Result.fail().message("交易号不正确!");
                }
            }
        }
        //删除交易号
        redisTemplate.delete("tradeNo:" + userId);
        //2:校验库存 不足的话由买家决定下一步如何 爱买不买
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            Boolean isHave = orderInfoService.hasStock(orderDetail);
            //2.1:无货
            if (!isHave) {
                return Result.fail().message(orderDetail.getSkuName() + "[库存不足]!");
            }
        }
        //3 4 5应属于同一事务
        //3:提交订单 (保存订单主表 订单详情表)
        //4:清除下过订单的购物车
        //5:开始计时 规定时间不付钱 取消订单
        //二维码 静态码:自己手动填金额 无失效时间
        //动态码:系统自动生成对应金额的二维码 默认有效时间2小时 延迟消息
        orderInfo.setUserId(Long.parseLong(userId));
        Long orderId = orderInfoService.insertOrder(orderInfo);
        return Result.ok(orderId);
    }

    //根据订单id查询订单对象
    @GetMapping("/auth/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable Long orderId) {
        return orderInfoService.getOrderInfo(orderId);
    }

    //拆单 由仓库微服务发起的 远程调用订单微服务 httpclient方式
    @PostMapping("/orderSplit")
    //?问号传参可直接接收
    public List<Map> orderSplit(Long orderId, String wareSkuMap) {
        //[{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
        //表示：sku为2号，10号的商品在1号仓库  sku为3号商品在2号仓库
        //开始拆单 子订单集合
        List<OrderInfo> subOrderInfoList = orderInfoService.orderSplit(orderId, wareSkuMap);
        //返回给库存系统
        //List<OrderInfo>->List<Map> 然后直接返回
        return subOrderInfoList.stream().map(subOrderInfo -> {
            //初始化仓库需要的数据即按照格式返回
            return orderInfoService.initWareOrder(subOrderInfo);
        }).collect(Collectors.toList());
    }
}
